<template>
  <div class="panorama" ref="panorama"></div>
</template>
<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import {
  CSS3DObject,
  CSS3DRenderer,
} from "three/examples/jsm/renderers/CSS3DRenderer";

import { onMounted, ref } from "vue";

export default {
  name: "Panorama",
};
</script>
<script setup>
import shengdan from "@/assets/brown_photostudio_02_4k.png";
import bzjkMp4 from "@/assets/bzjk.mp4";

const panorama = ref(null);
onMounted(() => {
  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera(
    70,
    window.innerWidth / window.innerHeight,
    0.1,
    100
  );
  camera.position.y = 5;
  const renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  panorama.value.appendChild(renderer.domElement);
  const DOM = panorama.value;

  const controls = new OrbitControls(camera, renderer.domElement);
  controls.enableDamping = true;
  controls.dampingFactor = 0.25;
  controls.enableZoom = true;
  controls.target.set(5, 2, 0);

  const light = new THREE.AmbientLight(0xffffff);
  light.position.set(0, 0, 0);
  scene.add(light);

  const geometry = new THREE.SphereGeometry(40, 512, 512);
  const material = new THREE.MeshBasicMaterial({
    map: new THREE.TextureLoader().load(shengdan),
    side: THREE.DoubleSide,
  });
  const sphere = new THREE.Mesh(geometry, material);

  const planeGeometry = new THREE.PlaneGeometry(32, 24);
  const video = document.createElement("video");
  video.src = bzjkMp4;
  video.loop = true;
  video.muted = true;
  video.play();
  const videoTexture = new THREE.VideoTexture(video);
  const planeMaterial = new THREE.MeshBasicMaterial({
    side: THREE.DoubleSide,
    map: videoTexture,
  });

  const plane = new THREE.Mesh(planeGeometry, planeMaterial);
  plane.position.set(20, 2, -24);
  plane.rotateY(-Math.PI / 6);
  scene.add(plane);
  scene.add(sphere);

  const axesHelper = new THREE.AxesHelper(5);
  scene.add(axesHelper);

  const buttonGeometry = new THREE.BoxGeometry(1, 1, 1);
  // 定义红色和绿色材质
  const greenMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
  const redMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
  const button = new THREE.Mesh(buttonGeometry, greenMaterial);
  button.position.set(20, 0, -24);
  button.userData.clickable = true;
  button.userData.isGreen = true; // 添加状态标记

  const raycaster = new THREE.Raycaster();
  const mouse = new THREE.Vector2();

  const zebraMaterial = new THREE.ShaderMaterial({
    uniforms: {
      time: { value: 0 },
      scale: { value: 20.0 },
      speed: { value: 0.0 },
      isMoving: { value: 0.0 },
    },
    vertexShader: `
    varying vec2 vUv;
    void main() {
      vUv = uv;
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
  `,
    fragmentShader: `
    varying vec2 vUv;
    uniform float scale;
    uniform float time;
    uniform float speed;
    uniform float isMoving;
    
    void main() {
      float offset = time * speed * isMoving;
      float pattern = step(0.5, fract((vUv.x + offset) * scale));
      vec3 color = mix(vec3(0.1), vec3(1.0), pattern);
      gl_FragColor = vec4(color, 1.0);
    }
  `,
  });

  const tubeGeometry = new THREE.TubeGeometry(
    new THREE.CatmullRomCurve3([
      new THREE.Vector3(0, 2, 4),
      new THREE.Vector3(3, 2, 6),
      new THREE.Vector3(10, 2, -3),
      new THREE.Vector3(12, 2, -4),
      new THREE.Vector3(10, 2, -3),
    ]),
    32,
    0.1,
    8,
    false
  );

  const tube = new THREE.Mesh(tubeGeometry, zebraMaterial);
  scene.add(tube);

  let isTextureMoving = false;

  function onClick(event) {
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

    raycaster.setFromCamera(mouse, camera);
    const intersects = raycaster.intersectObject(button);

    if (intersects.length > 0) {
      // 切换视频状态
      if (video.paused) {
        video.play();
      } else {
        video.pause();
      }

      // 切换纹理移动状态
      isTextureMoving = !isTextureMoving;
      zebraMaterial.uniforms.isMoving.value = isTextureMoving ? 1.0 : 0.0;
      zebraMaterial.uniforms.speed.value = isTextureMoving ? 0.5 : 0.0;

      // 切换按钮颜色
      button.userData.isGreen = !button.userData.isGreen;
      button.material = button.userData.isGreen ? greenMaterial : redMaterial;
    }
  }

  function onMouseMove(event) {
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

    raycaster.setFromCamera(mouse, camera);
    const intersects = raycaster.intersectObject(button);

    if (intersects.length > 0) {
      renderer.domElement.style.cursor = "pointer";
    } else {
      renderer.domElement.style.cursor = "default";
    }
  }

  renderer.domElement.addEventListener("click", onClick);
  renderer.domElement.addEventListener("mousemove", onMouseMove);

  scene.add(button);

  // CSS 3D DOM
  const cssRenderer = new setCss3DRenderer(DOM);
  // 添加iframe
  const iframe = document.createElement("iframe");
  iframe.src = "https://player.bilibili.com/player.html?aid=113608948254771&bvid=BV1MXikYNEQb&cid=27217759558";
  iframe.style.width = "100%";
  iframe.style.height = "80%";
  iframe.style.border = "none";
  const iframeMesh = new CSS3DObject(iframe);
  iframeMesh.position.set(20, 2, -14);
  // iframeMesh.scale.multiplyScalar(0.6);
  iframeMesh.rotateY(-Math.PI / 2);


  scene.add(iframeMesh);

  function animate() {
    requestAnimationFrame(animate);
    controls.update();
    zebraMaterial.uniforms.time.value += 0.016;
    renderer.render(scene, camera);
    cssRenderer.render(scene, camera);
  }
  animate();
});

function setCss3DRenderer(DOM) {

const css3DRender = new CSS3DRenderer()

css3DRender.resize = () => {

    css3DRender.setSize(DOM.clientWidth, DOM.clientHeight)

    css3DRender.domElement.style.zIndex = 0

    css3DRender.domElement.style.position = 'relative'

    css3DRender.domElement.style.top = -DOM.clientHeight + 'px'

    css3DRender.domElement.style.height = DOM.clientHeight + 'px'

    css3DRender.domElement.style.width = DOM.clientWidth + 'px'

    css3DRender.domElement.style.pointerEvents = 'none'

}

css3DRender.resize()

DOM.appendChild(css3DRender.domElement)

return css3DRender

}
</script>
<style scoped>
.panorama {
  width: 100%;
  height: 100vh;
}
</style>
